home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1990-91 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /* $Header: /scheme/microcode/RCS/wind.c,v 1.4 1991/07/06 21:42:41 cph Exp $ */
-
- #include <stdio.h>
- #include "obstack.h"
- #include "dstack.h"
- extern void EXFUN (free, (PTR ptr));
- #define obstack_chunk_alloc xmalloc
- #define obstack_chunk_free free
-
- extern void EXFUN (block_signals, (void));
- extern void EXFUN (unblock_signals, (void));
-
- static void
- DEFUN (error, (procedure_name, message),
- CONST char * procedure_name AND
- CONST char * message)
- {
- fprintf (stderr, "%s: %s\n", procedure_name, message);
- fflush (stderr);
- abort ();
- }
-
- static PTR
- DEFUN (xmalloc, (length), unsigned int length)
- {
- extern PTR EXFUN (malloc, (unsigned int length));
- PTR result = (malloc (length));
- if (result == 0)
- error ("malloc", "memory allocation failed");
- return (result);
- }
-
- struct winding_record
- {
- struct winding_record * next;
- void EXFUN ((*protector), (PTR environment));
- PTR environment;
- };
-
- static struct obstack dstack;
- static struct winding_record * current_winding_record;
- PTR dstack_position;
-
- void
- DEFUN_VOID (dstack_initialize)
- {
- obstack_init (&dstack);
- dstack_position = 0;
- current_winding_record = 0;
- }
-
- void
- DEFUN_VOID (dstack_reset)
- {
- block_signals ();
- obstack_free ((&dstack), 0);
- dstack_initialize ();
- unblock_signals ();
- }
-
- #define EXPORT(sp) ((PTR) (((char *) (sp)) + (sizeof (PTR))))
-
- PTR
- DEFUN (dstack_alloc, (length), unsigned int length)
- {
- PTR chunk;
- block_signals ();
- chunk = (obstack_alloc ((&dstack), ((sizeof (PTR)) + length)));
- (* ((PTR *) chunk)) = dstack_position;
- dstack_position = chunk;
- unblock_signals ();
- return (EXPORT (chunk));
- }
-
- void
- DEFUN (dstack_protect, (protector, environment),
- void EXFUN ((*protector), (PTR environment)) AND
- PTR environment)
- {
- struct winding_record * record =
- (dstack_alloc (sizeof (struct winding_record)));
- (record -> next) = current_winding_record;
- (record -> protector) = protector;
- (record -> environment) = environment;
- current_winding_record = record;
- }
-
- void
- DEFUN (dstack_alloc_and_protect, (length, initializer, protector),
- unsigned int length AND
- void EXFUN ((*initializer), (PTR environment)) AND
- void EXFUN ((*protector), (PTR environment)))
- {
- struct winding_record * record =
- (dstack_alloc ((sizeof (struct winding_record)) + length));
- PTR environment = (((char *) record) + (sizeof (struct winding_record)));
- (*initializer) (environment);
- (record -> next) = current_winding_record;
- (record -> protector) = protector;
- (record -> environment) = environment;
- current_winding_record = record;
- }
-
- void
- DEFUN (dstack_set_position, (position), PTR position)
- {
- block_signals ();
- #define DEBUG_DSTACK
- #ifdef DEBUG_DSTACK
- {
- PTR * sp = dstack_position;
- while (sp != position)
- {
- if (sp == 0)
- error ("dstack_set_position", "position argument not found");
- sp = (*sp);
- }
- }
- #endif /* DEBUG_DSTACK */
- while (dstack_position != position)
- {
- if (dstack_position == 0)
- error ("dstack_set_position", "no more stack");
- if ((EXPORT (dstack_position)) == current_winding_record)
- {
- PTR sp = dstack_position;
- struct winding_record * record = current_winding_record;
- /* Must unblock signals while the protector runs, and
- re-block afterwards, in case the protector does something
- to change the signal mask. Otherwise, the change to the
- signal mask will be undone when the final call to
- unblock_signals is performed. */
- unblock_signals ();
- (* (record -> protector)) (record -> environment);
- block_signals ();
- if (sp != dstack_position)
- error ("dstack_set_position", "stack slipped during unwind");
- current_winding_record = (record -> next);
- }
- {
- PTR * sp = dstack_position;
- dstack_position = (*sp);
- obstack_free ((&dstack), sp);
- }
- }
- unblock_signals ();
- }
-
- struct binding_record
- {
- PTR * location;
- PTR value;
- };
-
- static void
- DEFUN (undo_binding, (environment), PTR environment)
- {
- (* (((struct binding_record *) environment) -> location)) =
- (((struct binding_record *) environment) -> value);
- }
-
- static PTR * save_binding_location;
-
- static void
- DEFUN (save_binding, (environment), PTR environment)
- {
- (((struct binding_record *) environment) -> location) =
- save_binding_location;
- (((struct binding_record *) environment) -> value) =
- (*save_binding_location);
- }
-
- void
- DEFUN (dstack_bind, (location, value), PTR location AND PTR value)
- {
- save_binding_location = location;
- dstack_alloc_and_protect
- ((sizeof (struct binding_record)), save_binding, undo_binding);
- (* ((PTR *) location)) = value;
- }
-